1 using UnityEngine;
2 using
System;
3 using
System.Collections;
4 using
System.Collections.Generic;
5
6
7 ///
<summary>
8 ///
base class shared by the Tween and TweenChain classes to allow a seemless API when controlling
9 ///
either of them
10 ///
</summary>
11 public
abstract class AbstractGoTween
12 {
13     
public int id = 0; // optional id used for identifying this tween
14     
public GoTweenState state { get; protected set; } // current state of the tween
15     
public float duration { get; protected set; } // duration for a single loop
16     
public float totalDuration { get; protected set; } // duration for all loops of this tween
17     
public float timeScale { get; set; } // time scale to be used by this tween
18
19     
public GoUpdateType updateType { get; protected set; }
20     
public GoLoopType loopType { get; protected set; }
21     
public int iterations { get; protected set; } // set to -1 for infinite
22
23     
public bool autoRemoveOnComplete { get; set; } // should we automatically remove ourself from the Go's list of tweens when done?
24     
public bool isReversed { get; protected set; } // have we been reversed? this is different than a PingPong loop's backwards section
25     
public bool allowEvents { get; set; } // allow the user to surpress events.
26     
protected bool _didInit; // flag to ensure event only gets fired once
27     
protected bool _didBegin; // flag to ensure event only gets fired once
28     
protected bool _fireIterationStart;
29     
protected bool _fireIterationEnd;
30
31     
// internal state for update logic
32     
protected float _elapsedTime; // elapsed time for the current loop iteration
33     
protected float _totalElapsedTime; // total elapsed time of the entire tween
34     
public float totalElapsedTime { get { return _totalElapsedTime; } }
35
36     
protected bool _isLoopingBackOnPingPong;
37     
public bool isLoopingBackOnPingPong { get { return _isLoopingBackOnPingPong; } }
38
39     
protected bool _didIterateLastFrame;
40     
protected bool _didIterateThisFrame;
41     
protected int _deltaIterations; // change in completed iterations this frame.
42     
protected int _completedIterations;
43     
public int completedIterations { get { return _completedIterations; } }
44
45     
// action event handlers
46     
protected Action<AbstractGoTween> _onInit; // executes before initial setup.
47     
protected Action<AbstractGoTween> _onBegin; // executes when a tween starts.
48     
protected Action<AbstractGoTween> _onIterationStart; // executes whenever a tween starts an iteration.
49     
protected Action<AbstractGoTween> _onUpdate; // execute whenever a tween updates.
50     
protected Action<AbstractGoTween> _onIterationEnd; // executes whenever a tween ends an iteration.
51     
protected Action<AbstractGoTween> _onComplete; // exectures whenever a tween completes
52
53     
public void setOnInitHandler( Action<AbstractGoTween> onInit )
54     {
55         _onInit = onInit;
56     }
57
58     
public void setOnBeginHandler( Action<AbstractGoTween> onBegin )
59     {
60         _onBegin = onBegin;
61     }
62
63     
public void setonIterationStartHandler( Action<AbstractGoTween> onIterationStart )
64     {
65         _onIterationStart = onIterationStart;
66     }
67
68     
public void setOnUpdateHandler( Action<AbstractGoTween> onUpdate )
69     {
70         _onUpdate = onUpdate;
71     }
72
73     
public void setonIterationEndHandler( Action<AbstractGoTween> onIterationEnd )
74     {
75         _onIterationEnd = onIterationEnd;
76     }
77
78     
public void setOnCompleteHandler( Action<AbstractGoTween> onComplete )
79     {
80         _onComplete = onComplete;
81     }

82
83     ///
<summary>
84     ///
called once per tween when it is first updated
85     ///
</summary>
86     
protected virtual void onInit()
87     {
88         
if( !allowEvents )
89             
return;
90
91         
if( _onInit != null )
92             _onInit(
this );
93
94         _didInit =
true;
95     }

96
97     ///
<summary>
98     ///
called whenever the tween is updated and the playhead is at the start (or end, depending on isReversed) of the tween.
99     ///
</summary>
100     
protected virtual void onBegin()
101     {
102         
if( !allowEvents )
103             
return;
104
105         
if( isReversed && _totalElapsedTime != totalDuration )
106             
return;
107         
else if( !isReversed && _totalElapsedTime != 0f )
108             
return;
109
110         
if( _onBegin != null )
111             _onBegin(
this );
112
113         _didBegin =
true;
114     }

115
116
117     ///
<summary>
118     ///
called once per iteration at the start of the iteration.
119     ///
</summary>
120     
protected virtual void onIterationStart()
121     {
122         
if( !allowEvents )
123             
return;
124
125         
if( _onIterationStart != null )
126             _onIterationStart(
this );
127     }

128
129     ///
<summary>
130     ///
called once per update, after the update has occured.
131     ///
</summary>
132     
protected virtual void onUpdate()
133     {
134         
if( !allowEvents )
135             
return;
136
137         
if( _onUpdate != null )
138             _onUpdate(
this );
139     }

140
141     ///
<summary>
142     ///
called once per iteration at the end of the iteration.
143     ///
</summary>
144     
protected virtual void onIterationEnd()
145     {
146         
if( !allowEvents )
147             
return;
148
149         
if( _onIterationEnd != null )
150             _onIterationEnd(
this );
151     }

152
153
154     ///
<summary>
155     ///
called when the tween completes playing.
156     ///
</summary>
157     
protected virtual void onComplete()
158     {
159         
if( !allowEvents )
160             
return;
161
162         
if( _onComplete != null )
163             _onComplete(
this );
164     }

165
166
167     ///
<summary>
168     ///
tick method. if it returns true it indicates the tween is complete.
169     ///
note: at it's base, AbstractGoTween does not fire events, it is up to the implementer to
170     ///
do so. see GoTween and AbstractGoTweenCollection for examples.
171     ///
</summary>
172     
public virtual bool update( float deltaTime )
173     {
174         
// increment or decrement the total elapsed time then clamp from 0 to totalDuration
175         
if( isReversed )
176             _totalElapsedTime -= deltaTime;
177         
else
178             _totalElapsedTime += deltaTime;
179
180         _totalElapsedTime = Mathf.Clamp( _totalElapsedTime,
0, totalDuration );
181
182         _didIterateLastFrame = _didIterateThisFrame || ( !isReversed && _totalElapsedTime ==
0 ) || ( isReversed && _totalElapsedTime == totalDuration );
183
184         
// we flip between ceil and floor based on the direction, because we want the iteration change
185         
// to happen when "duration" seconds has elapsed, not immediately, as was the case if you
186         
// were doing a floor and were going in reverse.
187         
if( isReversed )
188             _deltaIterations = Mathf.CeilToInt( _totalElapsedTime / duration ) - _completedIterations;
189         
else
190             _deltaIterations = Mathf.FloorToInt( _totalElapsedTime / duration ) - _completedIterations;
191
192         
// we iterated this frame if we have done a goTo() to an iteration point, or we've passed over
193         
// an iteration threshold.
194         _didIterateThisFrame = !_didIterateLastFrame && ( _deltaIterations !=
0f || _totalElapsedTime % duration == 0f );
195
196         _completedIterations += _deltaIterations;
197
198         
// set the elapsedTime, given what we know.
199         
if( _didIterateLastFrame )
200         {
201             _elapsedTime = isReversed ? duration :
0f;
202         }
203         
else if( _didIterateThisFrame )
204         {
205             
// if we iterated this frame, we force the _elapsedTime to the end of the timeline.
206             _elapsedTime = isReversed ?
0f : duration;
207         }
208         
else
209         {
210             _elapsedTime = _totalElapsedTime % duration;
211
212             
// if you do a goTo(x) where x is a multiple of duration, we assume that you want
213             
// to be at the end of your duration, as this sets you up to have an automatic OnIterationStart fire
214             
// the next updated frame. the only caveat is when you do a goTo(0) when playing forwards,
215             
// or a goTo(totalDuration) when playing in reverse. we assume that at that point, you want to be
216             
// at the start of your tween.
217             
if( _elapsedTime == 0f && ( ( isReversed && _totalElapsedTime == totalDuration ) || ( !isReversed && _totalElapsedTime > 0f ) ) )
218             {
219                 _elapsedTime = duration;
220             }
221         }
222
223         
// we can only be looping back on a PingPong if our loopType is PingPong and we are on an odd numbered iteration
224         _isLoopingBackOnPingPong =
false;
225         
if( loopType == GoLoopType.PingPong )
226         {
227             
// due to the way that we count iterations, and force a tween to remain at the end
228             
// of it's timeline for one frame after passing the duration threshold,
229             
// we need to make sure that _isLoopingBackOnPingPong references the current
230             
// iteration, and not the next one.
231             
if( isReversed )
232             {
233                 _isLoopingBackOnPingPong = _completedIterations %
2 == 0;
234
235                 
if( _elapsedTime == 0f )
236                     _isLoopingBackOnPingPong = !_isLoopingBackOnPingPong;
237             }
238             
else
239             {
240                 _isLoopingBackOnPingPong = _completedIterations %
2 != 0;
241
242                 
if( _elapsedTime == duration )
243                     _isLoopingBackOnPingPong = !_isLoopingBackOnPingPong;
244             }
245         }
246
247         
// set a flag whether to fire the onIterationEnd event or not.
248         _fireIterationStart = _didIterateThisFrame || ( !isReversed && _elapsedTime == duration ) || ( isReversed && _elapsedTime ==
0f );
249         _fireIterationEnd = _didIterateThisFrame;
250
251         
// check for completion
252         
if( ( !isReversed && iterations >= 0 && _completedIterations >= iterations ) || ( isReversed && _totalElapsedTime <= 0 ) )
253             state = GoTweenState.Complete;
254
255         
if( state == GoTweenState.Complete )
256         {
257             
// these variables need to be reset here. if a tween were to complete,
258             
// and then get played again:
259             
// * The onIterationStart event would get fired
260             
// * tweens would flip their elapsedTime between 0 and totalDuration
261
262             _fireIterationStart =
false;
263             _didIterateThisFrame =
false;
264
265             
return true; // true if complete
266         }
267
268         
return false; // false if not complete
269     }

270
271
272     ///
<summary>
273     ///
subclasses should return true if they are a valid and ready to be added to the list of running tweens
274     ///
or false if not ready.
275     ///
technically, this should be marked as internal
276     ///
</summary>
277     
public abstract bool isValid();
278
279
280     ///
<summary>
281     ///
attempts to remove the tween property returning true if successful
282     ///
technically, this should be marked as internal
283     ///
</summary>
284     
public abstract bool removeTweenProperty( AbstractTweenProperty property );
285
286
287     ///
<summary>
288     ///
returns true if the tween contains the same type (or propertyName) property in its property list
289     ///
technically, this should be marked as internal
290     ///
</summary>
291     
public abstract bool containsTweenProperty( AbstractTweenProperty property );
292
293
294     ///
<summary>
295     ///
returns a list of all the TweenProperties contained in the tween and all its children (if it is
296     ///
a TweenChain or a TweenFlow)
297     ///
technically, this should be marked as internal
298     ///
</summary>
299     
public abstract List<AbstractTweenProperty> allTweenProperties();
300
301
302     ///
<summary>
303     ///
removes the Tween from action and cleans up its state
304     ///
</summary>
305     
public virtual void destroy()
306     {
307         state = GoTweenState.Destroyed;
308     }

309
310
311     ///
<summary>
312     ///
pauses playback
313     ///
</summary>
314     
public virtual void pause()
315     {
316         state = GoTweenState.Paused;
317     }

318
319
320     ///
<summary>
321     ///
resumes playback
322     ///
</summary>
323     
public virtual void play()
324     {
325         state = GoTweenState.Running;
326     }

327
328
329     ///
<summary>
330     ///
plays the tween forward. if it is already playing forward has no effect
331     ///
</summary>
332     
public void playForward()
333     {
334         
if( isReversed )
335             reverse();
336
337         play();
338     }

339
340
341     ///
<summary>
342     ///
plays the tween backwards. if it is already playing backwards has no effect
343     ///
</summary>
344     
public void playBackwards()
345     {
346         
if( !isReversed )
347             reverse();
348
349         play();
350     }

351
352
353     ///
<summary>
354     ///
resets the tween to the beginning, taking isReversed into account.
355     ///
</summary>
356     
protected virtual void reset( bool skipDelay = true )
357     {
358         goTo( isReversed ? totalDuration :
0, skipDelay );
359
360         _fireIterationStart =
true;
361     }

362
363
364     ///
<summary>
365     ///
rewinds the tween to the beginning (or end, depending on isReversed) and pauses playback.
366     ///
</summary>
367     
public virtual void rewind( bool skipDelay = true )
368     {
369         reset( skipDelay );
370         pause();
371     }

372
373
374     ///
<summary>
375     ///
rewinds the tween to the beginning (or end, depending on isReversed) and starts playback,
376     ///
optionally skipping delay (only relevant for Tweens).
377     ///
</summary>
378     
public void restart( bool skipDelay = true )
379     {
380         reset( skipDelay );
381         play();
382     }

383
384
385     ///
<summary>
386     ///
reverses playback. if going forward it will be going backward after this and vice versa.
387     ///
</summary>
388     
public virtual void reverse()
389     {
390         isReversed = !isReversed;
391
392         _completedIterations = isReversed ? Mathf.CeilToInt( _totalElapsedTime / duration ) : Mathf.FloorToInt( _totalElapsedTime / duration );
393
394         
// if we are at the "start" of the timeline, based on isReversed,
395         
// allow the onBegin/onIterationStart callbacks to fire again.
396         
if( ( isReversed && _totalElapsedTime == totalDuration ) || ( !isReversed && _totalElapsedTime == 0f ) )
397         {
398             _didBegin =
false;
399             _fireIterationStart =
true;
400         }
401     }

402
403
404     ///
<summary>
405     ///
completes the tween. sets the playhead to it's final position as if the tween completed normally.
406     ///
takes into account if the tween was playing forward or reversed.
407     ///
</summary>
408     
public virtual void complete()
409     {
410         
if( iterations < 0 )
411             
return;
412
413         
// set full elapsed time and let the next iteration finish it off
414         goTo( isReversed ?
0 : totalDuration, true );
415     }

416
417
418     ///
<summary>
419     ///
goes to the specified time clamping it from 0 to the total duration of the tween. if the tween is
420     ///
not playing it can optionally be force updated to the time specified. delays are not taken into effect.
421     ///
(must be implemented by inherited classes.)
422     ///
</summary>
423     
public abstract void goTo( float time, bool skipDelay = true );
424
425     ///
<summary>
426     ///
goes to the time and starts playback skipping any delays
427     ///
</summary>
428     
public void goToAndPlay( float time, bool skipDelay = true )
429     {
430         goTo( time, skipDelay );
431         play();
432     }

433
434
435     ///
<summary>
436     ///
waits for either completion or destruction. call in a Coroutine and yield on the return
437     ///
</summary>
438     
public IEnumerator waitForCompletion()
439     {
440         
while( state != GoTweenState.Complete && state != GoTweenState.Destroyed )
441             
yield return null;
442
443         
yield break;
444     }
445 }



Trò chơi Angry Birds trong UNITY Engine 31.685 lượt xem

Gõ tìm kiếm nhanh...